#include "HashTable.h"
#include <iostream>
#include <iomanip>
#include <string>
#include <math.h>
using namespace std;

HashTable::HashTable(string _name, int _size) {
    name = _name;
    size = _size;
    count = 0;
    table = new string[size];
}

int HashTable::hash(string s) {
    int t0 = s[0] % size;
    for (int i = 1; i < s.size(); i++)
        t0 = (5 * t0 + s[i]) % size;
    int j = 0;
    int t = t0;
    while (1) {
        if (full()) {
            resize();
            return hash(s);
        }
        if (table[t].empty()) {            
            table[t] = s;
            count++;
            return t;
        }
        if (table[t] == s)
            return t;
        j++;
        t = (t0 + rCoeff(j)) % size;
    }
}

int HashTable::rCoeff(int num) {
    int res = 1;
    for (int i = 0; i < num; i++)
        res = 5 * res;
    res = res % (4 * size);
    res /= 4;
    return res;
}

bool HashTable::full() {
    if (count == size)
        return true;
    return false;
}

bool HashTable::empty() {
    if (count == 0)
        return true;
    return false;
}

void HashTable::resize() {
    int n = size;
    size *= 2;
    count = 0;
    string* rtable = table;
    table = new string[size];
    for (int i = 0; i < n; i++)
        hash(rtable[i]); // �������������.
    delete[] rtable;
}

void HashTable::print() {
    if (empty())
        return;
    int n = log10((double) size);
    cout << "...................................." << endl;
    cout << "Name Table: " << name << endl;
    cout << "...................................." << endl;
    cout << "#";
    for (int i = 0; i < n; i++)
        cout << " ";
    cout << " : Element name" << endl;
    for (int i = 0; i < n; i++)
        cout << ".";
    cout << "..:..............................." << endl;
    cout.setf(ios::left);
    for (int i = 0; i < size; i++) {
        if (!table[i].empty()) {
            cout << setw(n + 1) << i;
            cout << " : " << table[i] << endl;
        }
    }
    cout << "...................................." << endl;
}

HashTable::~HashTable(void) {
    if (table)
        delete[] table;
}